package logic.ships.mothership;

import interfaces.spawnMenu.spawnMap.SpawnButtonContent.SpawnType;
import networking.messages.createMessages.ShipType;

import logic.SpawnLocation;
import logic.common.team.Team;
import logic.nodes.collision.DummyType;
import logic.nodes.collision.visibility.SightType;
import logic.ships.autoWeaponShip.AutoWeaponController;
import logic.ships.autoWeaponShip.AutoWeaponShip;
import logic.ships.autoWeaponShip.AutoWeaponTPController;
import logic.ships.autoWeaponShip.AutoWeaponShipProperties;
import logic.ships.autoWeaponShip.BlockFinder;
import logic.ships.carrier.Carrier;
import logic.ships.drone.Drone;
import logic.ships.frigate.Frigate;
import logic.ships.resourceShip.ResourceShip;
import logic.weapons.Weapon;
import logic.weapons.energyWeapons.EnergyWeapon;
import logic.weapons.projectileWeapons.heatSeeker.HeatSeekerWeapon;
import logic.weapons.projectileWeapons.missile.MissileWeapon;
import main.InitGame;
import map.spawnStation.SpawnPosition;

import com.jme.math.Vector3f;
import com.jme.scene.Node;

public class MotherShip extends ResourceShip implements AutoWeaponShip, SpawnPosition {
	
	private static final long serialVersionUID = 1L;
	
	private static int msID;
	
	private SpawnSlot droneSpawn, carrierSpawn, hunterSpawn;
	private BlockFinder energyBlockFinder, heatSeekerBlockFinder, missileBlockFinder;
	
	public MotherShip(String modelPath, String title, Node model, AutoWeaponShipProperties properties, Team team) {
		super(modelPath, title, model, properties, team, false, DummyType.None);
		
		SpawnSlotCreator creator = new SpawnSlotCreator(this);
		droneSpawn = creator.getDroneSpawn();
		carrierSpawn = creator.getCarrierSpawn();
		hunterSpawn = creator.getHunterSpawn();
		assert(droneSpawn != null);
		assert(carrierSpawn != null);
		assert(hunterSpawn != null);
		
		initBlockFinders();
		
		if(msID == 0 || msID > 2) msID = 1;
		objectID = msID;
		msID++;
		
		InitGame.get().getNetworkState().registerStaticObject(this);
		
		if(ingameState.getGame().getGameSetup().hasTeamStatusWindow()) 
			addController(new TeamProcessController(team));
	}
	
	private void initBlockFinders() {
		energyBlockFinder = new BlockFinder(this) {
			@Override
			public float getRange() { return getEnergyRange(); }
		};
		
		heatSeekerBlockFinder = new BlockFinder(this) {
			@Override
			public float getRange() { return getHeatSeekerRange(); }
		};
		
		missileBlockFinder = new BlockFinder(this) {
			@Override
			public float getRange() { return getMissileRange(); }
		};
	}
	
	@Override
	public float getActionRadius() { return 200f; }
	
	@Override
	public float getFireRangeOf(Weapon weapon) {
		if(weapon instanceof EnergyWeapon) return getEnergyRange();
		if(weapon instanceof HeatSeekerWeapon) return getHeatSeekerRange();
		if(weapon instanceof MissileWeapon) return getMissileRange();
		return Float.POSITIVE_INFINITY;
	}
	
	public float getEnergyRange() { return getMSProperties().getEnergyRange(); }
	
	public float getHeatSeekerRange() { return getMSProperties().getHeatSeekerRange(); }
	
	public float getMissileRange() { return getMSProperties().getMissileRange(); }
	
	@Override
	public void addWeapon(Weapon newWeapon) {
		super.addWeapon(newWeapon);
		
		if(!InitGame.get().isServer()) return;
		
		BlockFinder blockFinder = null;
		if(newWeapon instanceof EnergyWeapon) blockFinder = energyBlockFinder;
		else if(newWeapon instanceof HeatSeekerWeapon) blockFinder = heatSeekerBlockFinder;
		else if(newWeapon instanceof MissileWeapon) blockFinder = missileBlockFinder;
		
		if(blockFinder != null) {
			AutoWeaponController controller = new AutoWeaponController(newWeapon, this, blockFinder);
			newWeapon.addController(controller);
			new AutoWeaponTPController(this, newWeapon, blockFinder, controller);
		}
	}
	
	@Override
	public boolean canMove() {	return false; }
	
	@Override
	protected float getDistanceFactor() { return 3f; }
		
	public Vector3f getRandomDroneSpawn(Drone drone) {
		Vector3f spawn = droneSpawn.getRandomSpawn();
		if(spawn == null) {
			droneSpawn.addNode(drone);
			return null;
		}
		return spawn;
	}
	
	public Vector3f getRandomCarrierSpawn(Carrier carrier) {
		Vector3f spawn = carrierSpawn.getRandomSpawn();
		if(spawn == null) {
			carrierSpawn.addNode(carrier);
			return null;
		}
		return spawn;
	}
	
	public Vector3f getRandomFrigateSpawn(Frigate frigate) {
		Vector3f spawn = carrierSpawn.getRandomSpawn();
		if(spawn == null) {
			carrierSpawn.addNode(frigate);
			return null;
		}
		return spawn;
	}
	
	public boolean spawnsAreReady() {
		return carrierSpawn.getSlotMesh().getParent() == null 
		&& hunterSpawn.getSlotMesh().getParent() == null 
		&& droneSpawn.getSlotMesh().getParent() == null;
	}
	
	public AutoWeaponShipProperties getMSProperties() { return (AutoWeaponShipProperties)settings; }
	
	@Override
	public SightType getSightType() { return SightType.MotherShip; }
	
	@Override
	public float getDefaultScale() { return 4f; }
	
	@Override
	public int getDestroyMoney() { return 1000; }
	
	@Override
	protected ShipType getShipType() { return null; }
	
	@Override
	public SpawnLocation getSpawnLocation() { return hunterSpawn; }
	
	@Override
	public SpawnType getSpawnType() { return SpawnType.MotherShip; }
}